package ws

import (
	"context"
	"fmt"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
	"net/http"
	"serve/car/mq"
)

func Handle(w *websocket.Upgrader, sub mq.Subscriber, logger *zap.Logger) http.HandlerFunc {
	return func(writer http.ResponseWriter, request *http.Request) {
		upgrade, err := w.Upgrade(writer, request, nil)
		if err != nil {
			logger.Warn("cannot Upgrade", zap.Error(err))
			return
		}

		defer upgrade.Close()
		msgs, cleanUp, err := sub.Subscribe(context.Background())
		defer cleanUp()
		if err != nil {
			logger.Error("cannot subscribe", zap.Error(err))
			writer.WriteHeader(http.StatusInternalServerError)
			return
		}

		done := make(chan struct{})
		go func() {
			for {
				_, _, err := upgrade.ReadMessage()
				if err != nil {
					if !websocket.IsCloseError(err,
						websocket.CloseGoingAway,
						websocket.CloseNormalClosure) {
						fmt.Printf("upgrade ReadMessage%v\n", err)
						logger.Warn("upgrade ReadMessage", zap.Error(err))
					}
					done <- struct{}{}
					break
				}
			}
		}()

		for {
			select {
			case msg := <-msgs:
				err := upgrade.WriteJSON(msg)
				if err != nil {
					logger.Warn("cannot write json", zap.Error(err))
				}
			case <-done:
				return
			}
		}
	}
}
